import random
from deap import base, creator, tools, algorithms

# 定义染色体的基因：两个整数x和y
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
creator.create("Individual", list, fitness=creator.FitnessMax)

# 初始化工具盒
toolbox = base.Toolbox()

# 定义染色体（个体）的基因
toolbox.register("attr_int", random.randint, -10, 10)

# 定义如何从基因创建个体
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_int, n=2)

# 定义如何从个体创建种群
toolbox.register("population", tools.initRepeat, list, toolbox.individual)


# 定义评价函数，它通过检查x + y是否大于10来评估个体的适应性
def evalOneMax(individual):
    x, y = individual
    return (x + y > 10) * (x + y),


# 注册评价函数
toolbox.register("evaluate", evalOneMax)

# 注册遗传算法的操作
toolbox.register("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=1, indpb=0.1)
toolbox.register("select", tools.selTournament, tournsize=3)


# 仅执行遗传算法
def main():
    random.seed(64)

    # 创建种群
    pop = toolbox.population(n=50)

    # 评估初始种群
    fitnesses = list(map(toolbox.evaluate, pop))
    for ind, fit in zip(pop, fitnesses):
        ind.fitness.values = fit

    # 遗传算法的参数
    NGEN = 100
    CXPB = 0.5
    MUTPB = 0.2

    # 进行遗传算法的进化
    for i in range(NGEN):
        # 选择下一代个体
        offspring = toolbox.select(pop, len(pop))
        offspring = [toolbox.clone(ind) for ind in offspring]

        # 应用交叉和变异操作
        for child1, child2 in zip(offspring[::2], offspring[1::2]):
            if random.random() < CXPB:
                toolbox.mate(child1, child2)
                del child1.fitness.values
                del child2.fitness.values

        for mutant in offspring:
            if random.random() < MUTPB:
                toolbox.mutate(mutant)
                del mutant.fitness.values

        # 评估新个体的适应性
        invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
        fitnesses = map(toolbox.evaluate, invalid_ind)
        for ind, fit in zip(invalid_ind, fitnesses):
            ind.fitness.values = fit

        # 替换老一代
        pop[:] = offspring

        # 打印进度
        hall_of_fame = tools.HallOfFame(1)
        hall_of_fame.update(pop)
        record_hof = hall_of_fame.items[0]
        print("Generation %i, Best %s" % (i, record_hof))

    print("Best individual is %s, %s" % (record_hof, record_hof.fitness.values))


if __name__ == "__main__":
    main()